// Copyright (c) 2010, Anthony Cassidy
// All rights reserved.
// 
// Redistribution and use in source and binary forms, with or without modification, are 
// permitted provided that the following conditions are met:
// 
//     * Redistributions of source code must retain the above copyright notice, this list 
//         of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice, this 
//         list of conditions and the following disclaimer in the documentation and/or 
//         other materials provided with the distribution.
//     * Neither the name of the AntsAdventureGameCreator nor the names of its contributors 
//         may be used to endorse or promote products derived from this software without 
//         specific prior written permission.
// 
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
// THE POSSIBILITY OF SUCH DAMAGE.
#include "XStdafx.h"
#include "XInventory.h"
#include "XReceiver.h"

#include "XDiagnostics.h"



XInventory::XInventory()
{

    m_netRightArrowClicks = 0;
    m_blackImageForEmptySlot = QImage(1, 1, QImage::Format_ARGB32_Premultiplied);
    m_receiver = this;
    m_blackImageForEmptySlot.fill(0);
    m_allInventoryItemsForRoom.SetUpdateRectsCallback(this);
    m_isVisible = true;
}

XInventory::~XInventory()
{
    XDiagnostics::Delete("XInventory");
}

XInventoryItems& XInventory::Invs()
{ 
    return m_allInventoryItemsForRoom; 
}

XInventoryItems& XInventory::Items()
{ 
    return m_allInventoryItemsForRoom;
}

XInventorySlotCollection& XInventory::Slots()
{ 
    return m_slots;
}

XReceiver* XInventory::Receiver() const 
{ 
    return m_receiver;
}

bool XInventory::IsVisible() const 
{ 
    return m_isVisible;
}

bool XInventory::IsRightArrowVisible()
{
    return m_slots.Count() + m_netRightArrowClicks < m_visibleItemsCache.size();
}

bool XInventory::IsLeftArrowVisible()
{
    return m_netRightArrowClicks>0 && m_visibleItemsCache.size() >0;
}

void XInventory::DrawRightArrowIfVisible(QPoint mousePos, QPainter& displayPainter, QPainter& zbufferPainter, QRgb zbufferColor, bool forceRolloverOff)
{
    zbufferPainter.fillRect( m_rectForRightArrow, QBrush(zbufferColor));
    if(!IsRightArrowVisible())
    {
        displayPainter.drawImage(m_rectForRightArrow, m_blackImageForEmptySlot);
    }
    else if(m_rectForRightArrow.contains(mousePos))
    {
        displayPainter.drawImage(0,0,m_imageForRightArrowRollover);
    }
    else displayPainter.drawImage(0,0,m_imageForRightArrow);
}

void XInventory::DrawLeftArrowIfVisible(QPoint mousePos, QPainter& displayPainter, QPainter& zbufferPainter, QRgb zbufferColor, bool forceRolloverOff)
{
    zbufferPainter.fillRect( m_rectForLeftArrow, QBrush(zbufferColor));
    if(!IsLeftArrowVisible())
    {
        displayPainter.drawImage(m_rectForLeftArrow, m_blackImageForEmptySlot);
    }
    else if(m_rectForLeftArrow.contains(mousePos))
    {
        displayPainter.drawImage(0,0,m_imageForLeftArrowRollover);
    }
    else displayPainter.drawImage(0,0,m_imageForLeftArrow);
}


void XInventory::DrawSlotIfVisible(int i, QPainter& displayPainter, QPainter& zbufferPainter, QRgb zbufferColor)
{
    m_slots.DrawSlotIfVisible(i,displayPainter, zbufferPainter, zbufferColor);	
}

bool XInventory::IsMouseOverSlot(int i, QPoint pos)
{
    return m_slots.IsMouseOverSlot(i,pos);	
}

bool XInventory::IsMouseOverLeftArrow(QPoint pos)
{
    return m_rectForLeftArrow.contains(pos);
}

bool XInventory::IsMouseOverRightArrow(QPoint pos)
{
    return m_rectForRightArrow.contains(pos);
}

void XInventory::TriggerLeftArrow()
{
    m_netRightArrowClicks--; //relies on gui to enforce validity
    UpdateImages();
}

void XInventory::TriggerRightArrow()
{
    m_netRightArrowClicks++; //relies on gui to enforce validity
    UpdateImages();
}

void XInventory::TriggerSlot(int index)
{
    (index=index);
}

void WipeCanvas(QImage& image);


QImage  GenerateImageForInventoryArrowButton(Qt::ArrowType arrowType, QRect rect, bool isHighlight)
{
    QImage image(rect.right(), rect.bottom(), QImage::Format_ARGB32_Premultiplied);

    // set alpha channel BEFORE painter
    WipeCanvas(image);

    //initialize painter
    QPainter painter;
    bool isOk = painter.begin(&image);
    if(isOk)
    {
        //painter.fillRect(rect,Qt::black);
        int top = rect.top()+2;
        int bottom = rect.bottom()-2;
        int left = rect.left()+2;
        int right = rect.right()-2;
        int midy = (top+bottom)/2;
        int width = right - left;

        // different color
        if(isHighlight)
        {
            painter.setBrush(Qt::yellow);
        }
        else
        {
            painter.setBrush(Qt::blue);
        }

        // different shape 
        if(arrowType == Qt::RightArrow)
        {
            QPointF points[3] = {QPoint(right,midy),QPoint(left,midy-width),QPoint(left,midy+width)};
            painter.drawPolygon(points,3);
        }
        else
        {
            QPointF points[3] = {QPoint(left,midy),QPoint(right,midy-width),QPoint(right,midy+width)};
            painter.drawPolygon(points,3);
        }
        bool isOk2 = painter.end();
        (isOk2 = isOk2);
        ASSERT(isOk2 && "painter end failed");
    }

    return image;
}

void XInventory::ReviseNetRightArrowClicksDownIfNecessary()
{
    if(m_netRightArrowClicks >  m_visibleItemsCache.size() - m_slots.Count())
    {
        m_netRightArrowClicks = m_visibleItemsCache.size() - m_slots.Count();
    }

    if(m_netRightArrowClicks < 0)
    {
        m_netRightArrowClicks = 0;
    }
}

bool XInventory::IsInventoryItemAtSlot(int iSlot)
{
    ReviseNetRightArrowClicksDownIfNecessary();

    if(iSlot + m_netRightArrowClicks >= m_visibleItemsCache.size())
        return false;
    return true;
}


QPointer<XInventoryItem> XInventory::GetInventoryItemAtSlot(int iSlot)
{
    ReviseNetRightArrowClicksDownIfNecessary();

    if(iSlot + m_netRightArrowClicks >= m_visibleItemsCache.size())
    {
        ASSERT(false && "Bad Index for GetInventoryItemAtSlot. Maybe ZBuffer is returning wrong result?");
        return *new QPointer<XInventoryItem>; //leak memory better than crash
    }
    return m_visibleItemsCache[iSlot + m_netRightArrowClicks];
}

void XInventory::SetRect(QRect rect)
{
    m_rect = rect;
    UpdateRects();
}

void XInventory::UpdateRects()
{
    m_slots.ResizeRectList(m_rect, m_rectForLeftArrow, m_rectForRightArrow);
    UpdateImagesAndArrows();// a resize, ie redraw the arrows
}

void XInventory::UpdateItemVisibility()
{
    UpdateVisibleItemsCache();
    UpdateImages();// a re-assign
}

void XInventory::UpdateVisibleItemsCache() //only needs to be called on Visibility change callback
{
    Log::Inventory("-----------");
    m_visibleItemsCache.clear();
    unsigned int count = Items().Count();
    for(unsigned int i = 0;i<count;i++)
    {
        QPointer<XInventoryItem> item = m_allInventoryItemsForRoom.At(i);
        if(item->IsVisible())
        {
            Log::Inventory(item->FullPath());
            m_visibleItemsCache.push_back(item);
        }
    }
}


void XInventory::UpdateImagesAndArrows()
{
    // needs to be called when rect changes
    if(m_rectForRightArrow.right() != -1 && m_rectForRightArrow.bottom() != -1)
    {
        m_imageForRightArrow = GenerateImageForInventoryArrowButton(Qt::RightArrow, m_rectForRightArrow, false);
        m_imageForRightArrowRollover = GenerateImageForInventoryArrowButton(Qt::RightArrow, m_rectForRightArrow, true);
    }

    if(m_rectForLeftArrow.right() != -1 && m_rectForLeftArrow.bottom() != -1)
    {
        m_imageForLeftArrow = GenerateImageForInventoryArrowButton(Qt::LeftArrow, m_rectForLeftArrow, false);
        m_imageForLeftArrowRollover = GenerateImageForInventoryArrowButton(Qt::LeftArrow, m_rectForLeftArrow, true);
    }

    UpdateImages();
}

void XInventory::UpdateImages()
{
    ReviseNetRightArrowClicksDownIfNecessary();
    for(int i=0;i<m_slots.Count();i++)
    {
        if((i+m_netRightArrowClicks) < m_visibleItemsCache.size())
        {
            QImage bigInventoryImage = m_visibleItemsCache[i+m_netRightArrowClicks]->Image();
            m_slots.UpdateSlotImage(i,bigInventoryImage);
        }else
        {

            m_slots.UpdateSlotImage(i, m_blackImageForEmptySlot);
        }
    }
}

void XInventory::SetHighlightedSlot(int index)
{
    (index = index);
}
void XInventory::SetVisible(bool f)
{
    m_isVisible = f;
}

